package vpc.ext.vstack;

import java.io.IOException;
import java.io.PrintStream;
import vpc.core.Program;
import vpc.core.decl.Method;
import vpc.core.ProgramDecl.EntryPoint;
import vpc.sched.Stage;
import vpc.ext.vstack.util.Debug;
import vpc.ext.vstack.util.VstackException;
import java.util.*;

/**
 * This class is the main hook between the vstack project and the VPC Compiler. The method vpc.sched.Registry.initDefault()
 * must be modified to include the following line:
 * 
 * addStage("vstack", "tir->tir", vpc.ext.vstack.StackBoundStage.class);
 * 
 * The above line adds this class as a stage that the compiler can load. The vstack analysis is then invoked
 * as an option to the vpc compiler.
 * 
 * @author Philip Russell
 *
 */

public class StackBoundStage extends Stage {

	private static void debugEntryPoints(PrintStream out, Program p) {
		out.println("DEBUG: Printing entrypoints");
		for (EntryPoint e : p.programDecl.entryPoints) {
			out.println("\tEntryPoint = " + e.getName());
		}
		return;
	}

	public void visitProgram(Program program) throws IOException {

		// Initialize the debugging tools
		try {
			Debug.init(System.out);
		} catch (IOException e) {
			System.err
					.println("WARNING: could not load vstack debug properties.");
			e.printStackTrace();
		}

		// Initialize the GraphVisitor; this creates the root node, which is
		// the main method
		GraphVisitor gv = new GraphVisitor(program);

		//		debugEntryPoints(System.out, program);

		// Starting in the body of the main method, start the visitor pattern
		Method main = program.programDecl.mainEntry.method;
		gv.visitMethod(main, gv.rootContext);

		// Print the resulting graph if the option is set
		if (Debug.Flag.PRINTGRAPH.isSet()) {
			Debug.println(Debug.seperator1, Debug.Flag.PRINTGRAPH);
			gv.rootContext.root.printGraph(System.out, new HashSet<Node>());
		}

		try {
			System.out.println("maxStackPush() = "
					+ gv.rootContext.root.getMaxPush(new HashSet<Node>()));
		} catch (VstackException.CycleException c) {
			System.out.println("Cycle detected!");
		}

		return;
	}
}
